#from chp21_1metaClass import Entity
import abc

class AutoStorge:
    __counter = 0

    def __init__(self):
        cls = self.__class__
        prefix = cls.__name__
        index = cls.__counter
        self.storge_name = '{}#{}'.format(prefix,index)
        cls.__counter += 1
    
    def __set__(self,instance,value):
        if value > 0:
            instance.__dict__[self.storge_name] = value
    
    def __get__(self,instance,cls):
        if instance is None:
            return self
        return getattr(instance,self.storge_name)

class Validated(abc.ABC,AutoStorge):

    def __set__(self,inst,value):
        value = self.validate(inst,value)
        super().__set__(inst,value)

    @abc.abstractmethod
    def validate(self,inst,value):
        "在子类实现该抽象方法"

class Quantity(Validated):
    def validate(self,inst,value):
        if value > 0:
            return value

class NoBlank(Validated):
    def validate(self,inst,value):
        valueStr = str(value).strip()
        if len(valueStr) == 0:
            raise ValueError("value cannot be empty or blank")
        return value
#以上几个描述类的 实现了模板设计模式 抽象类给出一个模板方法 子类实现就可以了 而最顶层的父类AutoStorge实现了通用的功能



class LineItem():
    description = NoBlank()
    weight = Quantity()
    price = Quantity()

    def __init__(self,description,weight,price):
        self.description = description        
        # self.weight 首先访问自身有没有属性 没有就访问类属性 类属性是一个 Quantity 实例 为实例赋值会执行类方法 __set__
        self.weight = weight 
        self.price = price

    def subtotal(self):
        return self.weight * self.price